import math

sum_of_arithmetic_sequence = lambda begin, end, step: (begin + end) * ((end - begin) / step + 1) / 2


def test_perfect_num(n):
    factors = []
    for i in range(1, n):
        if n % i == 0:
            factors.append(i)
    if sum(factors) == n:
        return True, factors
    else:
        return False, factors


def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True


def sieve_of_eratosthenes(n):
    # Create a boolean array "prime[0..n]" and initialize all entries it as true.
    # A value in prime[i] will finally be false if i is Not a prime, else true.
    prime = [True for i in range(n + 1)]
    p = 2
    while p * p <= n:
        # If prime[p] is not changed, then it is a prime
        if prime[p]:
            # Update all multiples of p
            for i in range(p * p, n + 1, p):
                prime[i] = False
        p += 1
    return [p for p in range(2, n + 1) if prime[p]]


# Get user input:

n = int(input("Please input the value of integer n: "))

# Sum from 1 ~ n:

print("Sum from 1 ~ n is:", sum_of_arithmetic_sequence(1,n,1))

# All prime numbers from 1 ~ n:

print("All prime numbers from 1 ~ {}:".format(n))
print(sieve_of_eratosthenes(n))

# less efficient way: 
# for i in range(1, n + 1): if is_prime(i): print(i, end=' ')

# All perfect numbers from 1 ~ n:

print("All perfect numbers from 1 ~ {}:".format(n))
for i in range(1, n + 1):
    is_perfect, its_factors = test_perfect_num(i)
    if is_perfect:
        print(i, "is a perfect number, its factors are:", its_factors)


